#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "kernel.h"
//
#include "os.h"
//
#include "proto.h"
#include "events.h"
#include "mcode.h"

// this source file provides the API for claiming and generating HBP10GM events


#define MAXEVENTNO            16

typedef struct EVENTCLAIMANT EVENTCLAIMANT;

struct EVENTCLAIMANT {
  EVENTCLAIMANT *next;
  void *address;
  int r12;
};

EVENTCLAIMANT *claimants[MAXEVENTNO];


static _kernel_oserror err_no_room = { 1, "No room" };
static _kernel_oserror err_unknown_event = { 1, "Unknown event" };


void events_initialise() {

  int i;

  for (i = 0; i < MAXEVENTNO; i++)  claimants[i] = NULL;
}


void generate_event(unsigned int event, int arg1, int arg2, int arg3) {

  EVENTCLAIMANT *c;

  if (event > MAXEVENTNO)  return;
  c = claimants[event];
  while (c) {
    if (call_event_code(event, arg1, arg2, arg3, c->address, c->r12) == 0)
      c = NULL;
    else
      c = c->next;
  }
}


_kernel_oserror *events_install(unsigned int event, void *eventcode, int r12) {

  EVENTCLAIMANT *newc;

  if (event > MAXEVENTNO)  return &err_unknown_event;

  newc = malloc(sizeof(EVENTCLAIMANT));
  if (!newc)  return &err_no_room;
  newc->address = eventcode;
  newc->r12 = r12;
  newc->next = NULL;

  if (claimants[event]) {
    EVENTCLAIMANT *c;

    c = claimants[event];
    while (c->next)   c = c->next;
    c->next = newc;
  } else
    claimants[event] = newc;

  return NULL;
}


_kernel_oserror *events_remove(unsigned int event, void *eventcode, int r12) {

  EVENTCLAIMANT *c, *prev;

  c = claimants[event];
  if (!c)                  return &err_unknown_event;
  prev = NULL;
  while (c) {
    if ((c->address == eventcode) && (c->r12 == r12)) {
      if (prev == NULL)
        claimants[event] = NULL;
      else
        prev->next = c->next;
      free(c);
      c = NULL;
    } else {
      prev = c;
      c = c->next;
    }
  }

  return NULL;
}
